package com.daxue.localclient.service;

import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

import java.io.FileNotFoundException;
import java.time.LocalTime;

/**
 * @author daxue0929
 * @date 2022/09/03
 **/
@Service
public class RetryTest {

    /**
     * @Retryable(value = Exception.class,maxAttempts = 3,backoff = @Backoff(delay = 2000,multiplier = 1.5,maxDelay=360000L))
     * @Retryable ：
     * 注解方式标记当前方法会使用重试机制
     * 里面的 value： 重试的触发机制，当遇到Exception异常的时候，触发；
     *       maxAttempts： 重试的次数（包括第一次调用，也就是说如果设置3次，调用一次后，如果一直失败触发重试，那么还当前方法还会调用2次）；
     *       delay：重试的延迟时间，也就是距离上一次重试方法调用的间隔，单位毫秒
     *       multiplier： delay间隔时间的倍数，也就是说，第一次重试间隔如果是2000ms，那第二次重试的时候就是2000ms 乘以这个倍数1.5，就是3000ms；
     *       maxDelay:重试次数之间的最大时间间隔,默认为0,即忽略,如果小于delay的设置,则默认为30000L；
     *
     * @Retryable未生效可能原因
     * 1. @Retryable方法必须为 public
     * 2. 下面情况下@Retryable不生效，即重试方法与调用它的非重试方法在同一个类中
     * 3. 每个类中对一种异常只有一个重试方法。
     */
    @Retryable(value = {Exception.class, FileNotFoundException.class},
            maxAttempts = 3, backoff = @Backoff(delay = 2))

    public Integer retryThree(int code) throws Exception {
        System.out.println("dignifiedTest被调用,时间："+ LocalTime.now());
        if (code==0){
            System.out.println("retryThree throw");
            throw new Exception("把异常向外抛出去~");
        }
        System.out.println("dignifiedTest被调用,情况对头了！");

        return 200;
    }

    /**
     * @Recover未生效可能原因
     * 1. 返回值必须和被重试的函数返回值一致；
     * 2. 参数中除了第一个是触发的异常外，后面的参数需要和被重试函数的参数列表一致；
     * 3. 当然这里的返回值部分也可以再做一次手动重试，但是已经尝试那么多次都失败了，
     *    所以在兜底函数中再做一次也意义不大。因此我的考虑是，这里就用来做日志记录就好。
     * @param e
     * @return
     */
    @Recover
    public Integer recoverTest(Exception e, int code){
        System.out.println("recover 回调方法执行！！！！");
        //记日志到数据库 或者调用其余的方法
        return 400;
    }
}
